using System;
using System.Collections.Generic;
using Microsoft.Office.Interop.Outlook;
using System.IO;
using System.Runtime.InteropServices;
using Send2Sharepoint.Common;
using Send2Sharepoint.Copy;
using Exception = System.Exception;

namespace Send2Sharepoint.Outlook
{
    internal class GenericOutlookItem:IDisposable
    {
        private readonly object _mItem;
        private OlItemType _mItemType;
        private bool _mIsItemTypeInitialized;
        private readonly Repository.Repository _repository = new Repository.Repository(Globals.UserName, Globals.Password, Globals.SharepointSiteUrl);

        public GenericOutlookItem(object item)
        {
            _mItem = item;
        }

        public OlItemType ItemType
        {
            get
            {
            if (_mIsItemTypeInitialized)
                return _mItemType;

            if (_mItem is PostItem)
                _mItemType = OlItemType.olPostItem;
            else if (_mItem is MailItem)
                _mItemType = OlItemType.olMailItem;
            else if (_mItem is ContactItem)
                _mItemType = OlItemType.olContactItem;
            else if (_mItem is AppointmentItem)
                _mItemType = OlItemType.olAppointmentItem;
            else if (_mItem is TaskItem)
                _mItemType = OlItemType.olTaskItem;
            else if (_mItem is JournalItem)
                _mItemType = OlItemType.olJournalItem;
            else if (_mItem is DistListItem)
                _mItemType = OlItemType.olDistributionListItem;
            else if (_mItem is NoteItem)
                _mItemType = OlItemType.olNoteItem;

                _mIsItemTypeInitialized = true;
                return _mItemType;
            }
        }

        internal void Move(MAPIFolder destinationFolder)
        {
            if (_mItem is DocumentItem)
                ((DocumentItem)_mItem).Move(destinationFolder);
            else if (ItemType == OlItemType.olPostItem)
                ((PostItem)_mItem).Move(destinationFolder);
            else if (ItemType == OlItemType.olMailItem)
                ((MailItem)_mItem).Move(destinationFolder);
            else if (ItemType == OlItemType.olContactItem)
                ((ContactItem)_mItem).Move(destinationFolder);
            else if (ItemType == OlItemType.olAppointmentItem)
                ((AppointmentItem)_mItem).Move(destinationFolder);
            else if (ItemType == OlItemType.olTaskItem)
                ((TaskItem)_mItem).Move(destinationFolder);
            else if (ItemType == OlItemType.olJournalItem)
                ((JournalItem)_mItem).Move(destinationFolder);
            else if (ItemType == OlItemType.olDistributionListItem)
                ((DistListItem)_mItem).Move(destinationFolder);
            else if (ItemType == OlItemType.olNoteItem)
                ((NoteItem)_mItem).Move(destinationFolder);
        }


        private void UploadEmbeddedItem(Attachment attachment, IEnumerable<FieldInformation> indexInformation)
        {
            string tempFolderName = Path.GetTempPath();

            if (attachment.Type == OlAttachmentType.olEmbeddeditem)
            {
                try
                {
                    var tempAttachmentName = tempFolderName + attachment.FileName;
                    attachment.SaveAsFile(tempAttachmentName);
                                       
                    var tApp = new Application();
                    var tobj = tApp.CreateItemFromTemplate(tempAttachmentName, System.Reflection.Missing.Value);
                    var mailItem = (MailItem)tobj;
                    var destinationUrl = Globals.GetDestinationUrl(attachment.FileName);
                    var fileData = Globals.GetFileData(tempAttachmentName);
                    _repository.UploadFile2007(destinationUrl,fileData,indexInformation);
                    if (mailItem.Attachments.Count > 0)
                    {
                        foreach (Attachment a in mailItem.Attachments)
                        {
                            if (a.Type == OlAttachmentType.olEmbeddeditem)
                            {
                                UploadEmbeddedItem(a, indexInformation);
                            }
                            else
                            {
                                a.SaveAsFile(tempFolderName + a.FileName);
                                destinationUrl = Globals.GetDestinationUrl(a.FileName);
                                fileData = Globals.GetFileData(tempFolderName + a.FileName);
                                _repository.UploadFile2007(destinationUrl, fileData, indexInformation);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logging.WriteException(ex);
                    throw;
                }
            }
        }

        internal void Upload(IEnumerable<FieldInformation> indexInformation)
        {
            var tempFolderName = Path.GetTempPath();
            var tempFileName =
                Path.GetFileNameWithoutExtension(Path.Combine(tempFolderName, Path.GetTempFileName()));
            if (_mItem is DocumentItem)
            {
                try
                {
                    var documentItem = (DocumentItem)_mItem;
                    if (documentItem.Attachments.Count > 0)
                    {
                        foreach (Attachment attachment in documentItem.Attachments)
                        {
                            attachment.SaveAsFile(tempFolderName + attachment.FileName);

                            var destinationUrl = Globals.GetDestinationUrl(attachment.FileName);
                            var fileData = Globals.GetFileData(tempFolderName + attachment.FileName);
                            _repository.UploadFile2007(destinationUrl, fileData, indexInformation);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logging.WriteException(ex);
                    throw;
                }
            }

            switch (ItemType)
            {
                case OlItemType.olMailItem:
                    {
                        try
                        {
                            var mailItem = (MailItem)_mItem;
                            mailItem.SaveAs(tempFileName + ".msg", System.Reflection.Missing.Value);
                            var destinationUrl = Globals.GetDestinationUrl(mailItem.Subject + ".msg");
                            var fileData = Globals.GetFileData(tempFolderName + tempFileName + ".msg");
                            _repository.UploadFile2007(destinationUrl, fileData, indexInformation);
                            if (mailItem.Attachments.Count > 0)
                            {
                                foreach (Attachment attachment in mailItem.Attachments)
                                {
                                    if (attachment.Type == OlAttachmentType.olEmbeddeditem)
                                    {
                                        UploadEmbeddedItem(attachment, indexInformation);
                                    }
                                    else
                                    {
                                        attachment.SaveAsFile(tempFolderName + attachment.FileName);
                                        destinationUrl = Globals.GetDestinationUrl(attachment.FileName);
                                        fileData = Globals.GetFileData(tempFolderName + attachment.FileName);
                                        _repository.UploadFile2007(destinationUrl, fileData, indexInformation);
                                    }
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Logging.WriteException(ex);
                            throw;
                        }
                    }
                    break;
                case OlItemType.olPostItem:
                    {
                        try
                        {
                            var postItem = (PostItem)_mItem;
                            postItem.SaveAs(tempFolderName + tempFileName + ".oft", System.Reflection.Missing.Value);
                            var destinationUrl = Globals.GetDestinationUrl(postItem.Subject) + ".oft";
                            var fileData = Globals.GetFileData(tempFolderName + tempFileName + ".oft");
                            _repository.UploadFile2007(destinationUrl, fileData, indexInformation);
                            if (postItem.Attachments.Count > 0)
                            {
                                foreach (Attachment attachment in postItem.Attachments)
                                {
                                    attachment.SaveAsFile(tempFolderName + attachment.FileName);
                                    destinationUrl = Globals.GetDestinationUrl(attachment.FileName);
                                    fileData = Globals.GetFileData(tempFolderName + attachment.FileName);
                                    _repository.UploadFile2007(destinationUrl, fileData, indexInformation);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Logging.WriteException(ex);
                            throw;
                        }
                    }
                    break;
                case OlItemType.olContactItem:
                    {
                        try
                        {
                            var contactItem = (ContactItem)_mItem;
                            contactItem.SaveAs(tempFolderName + tempFileName + ".oft", System.Reflection.Missing.Value);
                            var destinationUrl = Globals.GetDestinationUrl(contactItem.Subject) + ".oft";
                            var fileData = Globals.GetFileData(tempFolderName + tempFileName + ".oft");
                            _repository.UploadFile2007(destinationUrl, fileData, indexInformation);
                            if (contactItem.Attachments.Count > 0)
                            {
                                foreach (Attachment attachment in contactItem.Attachments)
                                {
                                    attachment.SaveAsFile(tempFolderName + attachment.FileName);
                                    destinationUrl = Globals.GetDestinationUrl(attachment.FileName);
                                    fileData = Globals.GetFileData(tempFolderName + attachment.FileName);
                                    _repository.UploadFile2007(destinationUrl, fileData, indexInformation);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Logging.WriteException(ex);
                            throw;
                        }
                    }
                    break;
                case OlItemType.olAppointmentItem:
                    {
                        try
                        {
                            var appointmentItem = (AppointmentItem)_mItem;
                            appointmentItem.SaveAs(tempFolderName + tempFileName + ".oft", System.Reflection.Missing.Value);
                            var destinationUrl = Globals.GetDestinationUrl(appointmentItem.Subject) + ".oft";
                            var fileData = Globals.GetFileData(tempFolderName + tempFileName + ".oft");
                            _repository.UploadFile2007(destinationUrl, fileData, indexInformation);
                            if (appointmentItem.Attachments.Count > 0)
                            {
                                foreach (Attachment attachment in appointmentItem.Attachments)
                                {
                                    attachment.SaveAsFile(tempFolderName + attachment.FileName);
                                    destinationUrl = Globals.GetDestinationUrl(attachment.FileName);
                                    fileData = Globals.GetFileData(tempFolderName + attachment.FileName);
                                    _repository.UploadFile2007(destinationUrl, fileData, indexInformation);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Logging.WriteException(ex);
                            throw;
                        }
                    }
                    break;
                case OlItemType.olTaskItem:
                    {
                        try
                        {
                            var taskItem = (TaskItem)_mItem;
                            taskItem.SaveAs(tempFolderName + tempFileName + ".oft", System.Reflection.Missing.Value);
                            var destinationUrl = Globals.GetDestinationUrl(taskItem.Subject) + ".oft";
                            var fileData = Globals.GetFileData(tempFolderName + tempFileName + ".oft");
                            _repository.UploadFile2007(destinationUrl, fileData, indexInformation);
                            if (taskItem.Attachments.Count > 0)
                            {
                                foreach (Attachment attachment in taskItem.Attachments)
                                {
                                    attachment.SaveAsFile(tempFolderName + attachment.FileName);
                                    destinationUrl = Globals.GetDestinationUrl(attachment.FileName);
                                    fileData = Globals.GetFileData(tempFolderName + attachment.FileName);
                                    _repository.UploadFile2007(destinationUrl, fileData, indexInformation);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Logging.WriteException(ex);
                            throw;
                        }
                    }
                    break;
                case OlItemType.olJournalItem:
                    {
                        try
                        {
                            var journalItem = (JournalItem)_mItem;
                            journalItem.SaveAs(tempFolderName + tempFileName + ".oft", System.Reflection.Missing.Value);
                            var destinationUrl = Globals.GetDestinationUrl(journalItem.Subject) + ".oft";
                            var fileData = Globals.GetFileData(tempFolderName + tempFileName + ".oft");
                            _repository.UploadFile2007(destinationUrl, fileData, indexInformation);
                            if (journalItem.Attachments.Count > 0)
                            {
                                foreach (Attachment attachment in journalItem.Attachments)
                                {
                                    attachment.SaveAsFile(tempFolderName + attachment.FileName);
                                    destinationUrl = Globals.GetDestinationUrl(attachment.FileName);
                                    fileData = Globals.GetFileData(tempFolderName + attachment.FileName);
                                    _repository.UploadFile2007(destinationUrl, fileData, indexInformation);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Logging.WriteException(ex);
                            throw;
                        }
                    }
                    break;
                case OlItemType.olDistributionListItem:
                    {
                        try
                        {
                            var dlItem = (DistListItem)_mItem;
                            dlItem.SaveAs(tempFolderName + tempFileName + ".oft", System.Reflection.Missing.Value);
                            var destinationUrl = Globals.GetDestinationUrl(dlItem.Subject) + ".oft";
                            var fileData = Globals.GetFileData(tempFolderName + tempFileName + ".oft");
                            _repository.UploadFile2007(destinationUrl, fileData, indexInformation);
                            if (dlItem.Attachments.Count > 0)
                            {
                                foreach (Attachment attachment in dlItem.Attachments)
                                {
                                    attachment.SaveAsFile(tempFolderName + attachment.FileName);
                                    destinationUrl = Globals.GetDestinationUrl(attachment.FileName);
                                    fileData = Globals.GetFileData(tempFolderName + attachment.FileName);
                                    _repository.UploadFile2007(destinationUrl, fileData, indexInformation);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Logging.WriteException(ex);
                            throw;
                        }
                        break;
                    }
                case OlItemType.olNoteItem:
                    {
                        try
                        {
                            var noteItem = (NoteItem)_mItem;
                            noteItem.SaveAs(tempFolderName + tempFileName + ".oft", System.Reflection.Missing.Value);
                            var destinationUrl = Globals.GetDestinationUrl(noteItem.Subject) + ".oft";
                            var fileData = Globals.GetFileData(tempFolderName + tempFileName + ".oft");
                            _repository.UploadFile2007(destinationUrl, fileData, indexInformation);
                        }
                        catch (Exception ex)
                        {
                            Logging.WriteException(ex);
                            throw;
                        }
                        break;
                    }
            }
        }

        #region IDisposable Members

        public void Dispose()
        {
            Marshal.ReleaseComObject(_mItem);
        }

        #endregion

    }
}
